﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace miniCCR
{

    



    public class TaskSate
    {

        

        public IEnumerator<iTask> _Task = null;

        

        public bool MoveNext()
        {
            return true;
        }

        public void SetTask(IEnumerator<iTask> Task)
        {
            _Task = Task;
        }

        public void Run()
        {

        }
    }


    public abstract class GComponent
    {

        public GObject _Owner;

        //public abstract String GetCompType();

        public abstract uint _ComID { get;  }
        
        //public uint _ComID;

        public delegate IEnumerator<iTask> operationTask(Operation op);

        
        public TaskSate _TS = new TaskSate();

        

        Queue<Operation> _Queue = new Queue<Operation>();


        Dictionary<String, operationTask> _OperationMap = new Dictionary<string, operationTask>();


        //public void TaskRun(Operation op)
        //{
        //    Operation op;

        //    while (_Queue.TryDequeue(out op) == true)
        //    {

        //        _Task = OnMessage(op);

        //        while (_Task.MoveNext() == true)
        //        {


        //            return;
        //        }
        //    }

        //}

        public void AddMessageMap(String s, operationTask t)
        {
            _OperationMap.Add(s, t);
        }


        public virtual IEnumerator<miniCCR.iTask> InitHandle(Init op)
        {
            yield break;
        }


        public virtual IEnumerator<miniCCR.iTask> OnMessage(Operation op)
        {

            if (op.ToString() == typeof(Init).ToString())
                return InitHandle(op as Init);


            return null;
        }

        private bool TryWaitOperation(Operation op)
        {
            if (_TS._Task != null && _TS._Task.Current.TrySetWaitOP(op))
            {
                return true;
            }

            return false;
            
        }


        private void Run()
        {
            while (_TS._Task != null)
            {
                if (_TS._Task.MoveNext() == false)
                {

                    // 리턴코드 인지 보고 스택에 쌓아야함
                    //_TS._Task.

                    _TS._Task = null;
                }
                else
                {
                    if (_TS._Task.Current.Do() == false)
                        break;

                }

            }
        }


        public void Post(Operation op)
        {

            foreach (var item in _Queue)
            {
                if (item.GetType().Name == op.GetType().Name)
                    return;
            }

            
            if( TryWaitOperation(op))
            {
                Run();
            }else
            {
                _Queue.Enqueue(op);
            }
            

            while(_Queue.Count != 0)
            {
                op = _Queue.Peek();

                
                if( TryWaitOperation(op))
                {
                    Run();
                }
                else if (_TS._Task == null)
                {
                    _TS._Task = OnMessage(op);

                    Run();

                }
                else
                {
                    break;
                }

                _Queue.Dequeue();
            }


            //if (_TS._Task == null)
            //{
            //    _TS.SetTask(_OperationMap[op.ToString()](op));
                
            //    _TS.();
                
            //}
            //else
            //{
            //    if (_TS.IsWaitOperation(op))
            //    {
            //        _TS.MoveNext(op);
            //    }
            //    else
            //    {
                    
            //    }
                               
            //}

            ////if (_Task == null)
            ////{
            ////    _Task = _OperationMap[op.ToString()](op);
            ////}
            ////else
            //{
            //    _Queue.Enqueue(op);
            //}
            
                        
            ////ThreadPool.QueueUserWorkItem(TaskRun);

            ////if (_Task == null)
            ////{
            ////    TaskRun();
            ////}

        }



        public abstract string GetProxyName();

        public abstract miniCCR.Proxy GetProxy(GComponent from);

    }
}
